/**
 * Request模式流程诊断测试
 * 逐步分析预约流程，找出被拦截的原因
 */

import { mkdir, writeFile } from 'node:fs/promises'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { getPageParser } from '../src/main/automation/page-parser'
import { loadConfig } from '../src/main/config/index'
import { setupLogger } from '../src/main/logger/index'
import { HttpSession } from '../src/main/request/http-session'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const projectRoot = join(__dirname, '..')

// 先注册路径别名（如果 tsconfig-paths 可用）
// 使用同步方式或者移除这个依赖
try {
  // 尝试动态导入，但不使用 top-level await
  import('tsconfig-paths').then((tsconfigPaths) => {
    tsconfigPaths.register({
      baseUrl: projectRoot,
      paths: {
        '@shared/*': ['src/shared/*'],
        '@renderer/*': ['src/renderer/src/*'],
      },
    })
  }).catch(() => {
    // tsconfig-paths 未安装，tsx 可能会自动处理路径别名
  })
}
catch {
  // 忽略
}

const BASE_URL = 'https://abs1.td.gov.hk/tdab2/tdabs_external/AdminServlet_tchinese'
const SNAPSHOT_DIR = join(projectRoot, 'request-diagnosis-snapshots')

// 保存HTML快照
async function saveSnapshot(name: string, html: string, metadata: any = {}) {
  await mkdir(SNAPSHOT_DIR, { recursive: true })
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
  const filename = `${timestamp}_${name}.html`
  const filepath = join(SNAPSHOT_DIR, filename)
  await writeFile(filepath, html, 'utf8')

  const meta = {
    ...metadata,
    timestamp: new Date().toISOString(),
    filename,
  }
  const metaPath = join(SNAPSHOT_DIR, `${timestamp}_${name}_meta.json`)
  await writeFile(metaPath, JSON.stringify(meta, null, 2), 'utf8')

  console.log(`  ✓ 快照已保存: ${filename}`)
  return { html, filepath, metadata: meta }
}

// 分析页面内容
function analyzePage(html: string, stepName: string) {
  console.log(`\n📄 分析: ${stepName}`)
  console.log('─'.repeat(60))

  const checks = [
    { key: 'isHome', test: html.includes('cmdShowHome') || html.includes('预约首页') || html.includes('開始預約') },
    { key: 'isTerms', test: html.includes('cmdStartNewApplication') || html.includes('條款') },
    { key: 'isPersonalInfo', test: html.includes('cmdInputPersonalInfo') || html.includes('選擇服務') },
    { key: 'isIdentityCheck', test: html.includes('cmdCheckIdentifierAction') },
    { key: 'isPhoneInput', test: html.includes('電話號碼') || html.includes('電話號碼填寫') },
    { key: 'isOfficeSelect', test: html.includes('選擇牌照事務處') || html.includes('officeSelect') },
    { key: 'isCalendar', test: html.includes('cmdGetCalendarAction') || html.includes('onClickDate') || html.includes('calendar-table') },
    { key: 'isTimeslot', test: html.includes('cmdGetTimeslotListAction') || html.includes('onClickTimeslot') },
    { key: 'isConfirm', test: html.includes('cmdConfirmAppointment') || html.includes('確認') },
    { key: 'isSubmit', test: html.includes('cmdSubmitAppointmentAction') },
    { key: 'hasError', test: html.includes('系統繁忙') || html.includes('錯誤') || html.includes('512-E-') },
    { key: 'hasSessionExpired', test: html.includes('會話') && html.includes('超時') },
    { key: 'hasBlocked', test: html.includes('512-E-0044') || html.includes('重複登入') },
    { key: 'hasCalendarYear', test: html.includes('storedAppointmentCalendarYear') },
    { key: 'hasCalendarMonth', test: html.includes('storedAppointmentCalendarMonth') },
    { key: 'hasFormFrmAppointment', test: html.includes('form') && html.includes('frmAppointment') },
  ]

  const result: Record<string, boolean> = {}
  for (const { key, test } of checks) {
    result[key] = test
    const icon = test ? '✓' : '✗'
    const label = key.replace(/([A-Z])/g, ' $1').trim()
    console.log(`  ${icon} ${label}`)
  }

  return result
}

// 测试步骤1: 访问首页
async function testStep1(session: HttpSession) {
  console.log('\n🔍 步骤1: 访问首页')
  console.log('='.repeat(60))

  const url = `${BASE_URL}?cmd=cmdShowHome`
  console.log(`请求: GET ${url}`)

  const response = await session.request({ method: 'GET', url })
  const analysis = analyzePage(response.body, '首页响应')

  await saveSnapshot('01_home', response.body, {
    step: 1,
    url: response.url,
    status: response.status,
    analysis,
  })

  const parser = getPageParser()
  const formFields = parser.extractFormFields(response.body, 'frmAppointment')
  const fieldCount = formFields.success && formFields.data ? Object.keys(formFields.data).length : 0
  console.log(`\n  📋 表单字段数量: ${fieldCount}`)

  if (formFields.success && formFields.data) {
    const keyFields = ['storedAppointmentOperation', 'timestamp', 'announcementMessage']
    console.log(`  📋 关键字段:`)
    for (const field of keyFields) {
      if (formFields.data[field]) {
        const value = String(formFields.data[field])
        const preview = value.length > 50 ? `${value.substring(0, 50)}...` : value
        console.log(`    - ${field}: ${preview}`)
      }
    }
  }

  return { response, analysis, formFields }
}

// 测试步骤2: 开始预约（同意条款）
async function testStep2(session: HttpSession, step1Result: any) {
  console.log('\n🔍 步骤2: 开始预约（同意条款）')
  console.log('='.repeat(60))

  const baseFields = step1Result.formFields.success && step1Result.formFields.data ? step1Result.formFields.data : {}
  const payload: Record<string, string> = {
    ...baseFields,
    storedAppointmentOperation: 'A',
    timestamp: Date.now().toString(),
  }

  const url = `${BASE_URL}?cmd=cmdStartNewApplication`
  console.log(`请求: POST ${url}`)
  console.log(`  载荷字段数: ${Object.keys(payload).length}`)

  const response = await session.postForm(url, payload, step1Result.response.url)
  const analysis = analyzePage(response.body, '条款页响应')

  await saveSnapshot('02_terms', response.body, {
    step: 2,
    url: response.url,
    status: response.status,
    analysis,
    payloadSize: Object.keys(payload).length,
  })

  const parser = getPageParser()
  const formFields = parser.extractFormFields(response.body, 'frmAppointment')
  console.log(`\n  📋 表单字段数量: ${formFields.success && formFields.data ? Object.keys(formFields.data).length : 0}`)

  return { response, analysis, formFields }
}

// 测试步骤3: 进入个人信息页
async function testStep3(session: HttpSession, step2Result: any) {
  console.log('\n🔍 步骤3: 进入个人信息页')
  console.log('='.repeat(60))

  const baseFields = step2Result.formFields.success && step2Result.formFields.data ? step2Result.formFields.data : {}
  const payload: Record<string, string> = {
    ...baseFields,
    storedAppointmentOperation: 'A',
    timestamp: Date.now().toString(),
  }

  const url = `${BASE_URL}?cmd=cmdInputPersonalInfo`
  console.log(`请求: POST ${url}`)

  const response = await session.postForm(url, payload, step2Result.response.url)
  const analysis = analyzePage(response.body, '个人信息页响应')

  await saveSnapshot('03_personal_info', response.body, {
    step: 3,
    url: response.url,
    status: response.status,
    analysis,
  })

  const parser = getPageParser()
  const formFields = parser.extractFormFields(response.body, 'frmAppointment')

  // 检查是否有DI服务按钮
  const hasDIService = response.body.includes('onClickDISevType') || response.body.includes('免試簽發')
  console.log(`\n  ${hasDIService ? '✓' : '✗'} 检测到DI服务选项`)

  return { response, analysis, formFields }
}

// 测试步骤4: 提交身份验证
async function testStep4(session: HttpSession, step3Result: any) {
  console.log('\n🔍 步骤4: 提交身份验证')
  console.log('='.repeat(60))

  const testData = {
    passport: 'CE2345678',
    license: '440123199012011234',
    name: '策大市',
    email: 'test@example.com',
    issuingCountry: 'CN',
    issuingAuthority: 'GD',
  }

  const baseFields = step3Result.formFields.success && step3Result.formFields.data ? step3Result.formFields.data : {}
  const payload: Record<string, string> = {
    ...baseFields,
    storedAppointmentOperation: 'A',
    storedAppointmentServiceType: 'DI',
    storedAppointmentLicenseType: 'P',
    storedAppointmentLicenseNumber: testData.passport,
    storedAppointmentLicenseNumber2: testData.license,
    storedAppointmentLicenseOwnerName: testData.name,
    storedAppointmentIssuingCountry: testData.issuingCountry,
    storedAppointmentIssuingAuthority: testData.issuingAuthority,
    storedAppointmentConfirmationEmail: testData.email,
    storedAppointmentReminderEmail: testData.email,
    storedAppointmentPhoneNumber: 'N/A',
    storedAppointmentExpiryDate: '11-11-1901',
    sendReminder: 'Y',
    inputType: 'N',
    transferOfOwnership: 'N',
    timestamp: Date.now().toString(),
  }

  const url = `${BASE_URL}?cmd=cmdCheckIdentifierAction`
  console.log(`请求: POST ${url}`)
  console.log(`  身份信息: ${testData.name} / ${testData.passport}`)

  const response = await session.postForm(url, payload, step3Result.response.url)
  const analysis = analyzePage(response.body, '身份验证响应')

  await saveSnapshot('04_identity_check', response.body, {
    step: 4,
    url: response.url,
    status: response.status,
    analysis,
  })

  const parser = getPageParser()
  const formFields = parser.extractFormFields(response.body, 'frmAppointment')

  // 检查是否被拦截
  if (analysis.hasError || analysis.hasBlocked) {
    console.log(`\n  ⚠️  检测到错误或拦截:`)
    if (analysis.hasBlocked)
      console.log(`    - 可能被拦截（512-E-0044）`)
    if (analysis.hasError)
      console.log(`    - 页面包含错误信息`)
  }

  return { response, analysis, formFields, testData }
}

// 测试步骤5: 填写电话号码（如果需要）
async function testStep5(session: HttpSession, step4Result: any) {
  console.log('\n🔍 步骤5: 处理电话填写（如果需要）')
  console.log('='.repeat(60))

  // 检查是否需要填写电话号码
  if (!step4Result.analysis.isPhoneInput) {
    console.log('  跳过：不需要填写电话号码')
    return step4Result
  }

  console.log('  需要填写电话号码')
  // 使用有效的香港电话号码格式（8位数字，以2、3、5、6、9开头）
  const testPhone = '21234567' // 测试用电话号码（以2开头，符合香港电话号码格式）

  // 重要：从步骤4的响应中提取所有表单字段（电话填写页面）
  const baseFields = step4Result.formFields.success && step4Result.formFields.data ? step4Result.formFields.data : {}
  const payload: Record<string, string> = {
    ...baseFields,
    storedAppointmentOperation: 'A',
    inputType: 'N',
    storedAppointmentPhoneNumber: testPhone,
    timestamp: Date.now().toString(),
  }

  console.log(`  从表单提取的字段数: ${Object.keys(baseFields).length}`)
  console.log(`  合并后的字段数: ${Object.keys(payload).length}`)

  const url = `${BASE_URL}?cmd=cmdCheckIdentifierAction`
  console.log(`请求: POST ${url}`)
  console.log(`  电话号码: ${testPhone}`)

  const response = await session.postForm(url, payload, step4Result.response.url)
  const analysis = analyzePage(response.body, '电话填写响应')

  await saveSnapshot('05_phone_input', response.body, {
    step: 5,
    url: response.url,
    status: response.status,
    analysis,
    phone: testPhone,
  })

  const parser = getPageParser()
  const formFields = parser.extractFormFields(response.body, 'frmAppointment')

  return { response, analysis, formFields }
}

// 测试步骤6: 选择办事处（如果需要）
async function testStep6(session: HttpSession, step5Result: any) {
  console.log('\n🔍 步骤6: 处理办事处选择（如果需要）')
  console.log('='.repeat(60))

  // 如果已经在日历页，跳过
  if (step5Result.analysis.isCalendar) {
    console.log('  已在日历页，跳过办事处选择')
    return step5Result
  }

  // 如果还在电话填写页，说明步骤5没有成功，返回错误
  if (step5Result.analysis.isPhoneInput) {
    console.log('  ⚠️  仍在电话填写页，可能需要重新提交')
    return step5Result
  }

  // 检查是否需要选择办事处
  const needOfficeSelect = step5Result.analysis.isOfficeSelect
    || step5Result.response.body.includes('選擇牌照事務處')
    || step5Result.response.body.includes('listLicenseCenter')

  if (!needOfficeSelect) {
    console.log('  跳过：不需要选择办事处，可能直接进入日历')
    // 尝试直接获取日历
    const baseFields = step5Result.formFields.success && step5Result.formFields.data ? step5Result.formFields.data : {}
    const payload: Record<string, string> = {
      ...baseFields,
      storedAppointmentOperation: 'A',
      storedAppointmentOfficeCode: baseFields.storedAppointmentOfficeCode || 'HKLO',
      timestamp: Date.now().toString(),
    }

    const url = `${BASE_URL}?cmd=cmdGetCalendarAction`
    console.log(`  直接尝试获取日历: POST ${url}`)
    const response = await session.postForm(url, payload, step5Result.response.url)
    const analysis = analyzePage(response.body, '直接获取日历响应')
    await saveSnapshot('06_direct_calendar', response.body, { step: 6, url: response.url, status: response.status, analysis })
    const parser = getPageParser()
    const formFields = parser.extractFormFields(response.body, 'frmAppointment')
    return { response, analysis, formFields }
  }

  console.log('  需要选择办事处')
  const officeCode = 'HKLO' // 香港牌照事务处

  const baseFields = step5Result.formFields.success && step5Result.formFields.data ? step5Result.formFields.data : {}
  const payload: Record<string, string> = {
    ...baseFields,
    storedAppointmentOperation: 'A',
    storedAppointmentOfficeCode: officeCode,
    storedAppointmentServiceType: baseFields.storedAppointmentServiceType || 'DI',
    storedAppointmentRequestChannel: baseFields.storedAppointmentRequestChannel || 'W',
    timestamp: Date.now().toString(),
  }

  const url = `${BASE_URL}?cmd=cmdGetCalendarAction`
  console.log(`请求: POST ${url}`)
  console.log(`  办事处: ${officeCode}`)
  console.log(`  载荷字段数: ${Object.keys(payload).length}`)

  const response = await session.postForm(url, payload, step5Result.response.url)
  const analysis = analyzePage(response.body, '办事处选择响应')

  await saveSnapshot('06_office_select', response.body, {
    step: 6,
    url: response.url,
    status: response.status,
    analysis,
    officeCode,
  })

  const parser = getPageParser()
  const formFields = parser.extractFormFields(response.body, 'frmAppointment')

  return { response, analysis, formFields }
}

// 测试步骤7: 获取日历
async function testStep7(session: HttpSession, step6Result: any) {
  console.log('\n🔍 步骤7: 获取日历')
  console.log('='.repeat(60))

  // 如果已经在日历页，跳过
  if (step6Result.analysis.isCalendar) {
    console.log('  已在日历页，跳过获取')
    return step6Result
  }

  const baseFields = step6Result.formFields.success && step6Result.formFields.data ? step6Result.formFields.data : {}
  const payload: Record<string, string> = {
    ...baseFields,
    storedAppointmentOperation: 'A',
    storedAppointmentOfficeCode: baseFields.storedAppointmentOfficeCode || 'HKLO',
    timestamp: Date.now().toString(),
  }

  const url = `${BASE_URL}?cmd=cmdGetCalendarAction`
  console.log(`请求: POST ${url}`)

  const response = await session.postForm(url, payload, step6Result.response.url)
  const analysis = analyzePage(response.body, '日历页响应')

  await saveSnapshot('07_calendar', response.body, {
    step: 7,
    url: response.url,
    status: response.status,
    analysis,
  })

  const parser = getPageParser()
  const formFields = parser.extractFormFields(response.body, 'frmAppointment')
  const datesResult = parser.parseAvailableDates(response.body)

  const dateCount = datesResult.success && datesResult.data ? datesResult.data.length : 0
  console.log(`\n  📅 可用日期数量: ${dateCount}`)
  if (datesResult.success && datesResult.data && datesResult.data.length > 0) {
    console.log(`  📅 可用日期: ${datesResult.data.slice(0, 5).join(', ')}${datesResult.data.length > 5 ? '...' : ''}`)
  }

  return { response, analysis, formFields, datesResult }
}

// 主测试流程
async function runDiagnosis() {
  console.log('Request模式诊断测试')
  console.log('='.repeat(60))
  console.log(`快照目录: ${SNAPSHOT_DIR}`)
  console.log(`时间: ${new Date().toISOString()}`)
  console.log('='.repeat(60))

  await loadConfig()
  await setupLogger()

  const session = new HttpSession()

  try {
    // 步骤1: 首页
    const step1 = await testStep1(session)

    if (!step1.analysis.isHome) {
      console.log('\n⚠️  警告: 首页响应可能不正确')
    }

    // 步骤2: 条款页
    const step2 = await testStep2(session, step1)

    if (!step2.analysis.isTerms) {
      console.log('\n⚠️  警告: 条款页响应可能不正确')
    }

    // 步骤3: 个人信息页
    const step3 = await testStep3(session, step2)

    if (!step3.analysis.isPersonalInfo) {
      console.log('\n⚠️  警告: 个人信息页响应可能不正确')
    }

    // 步骤4: 身份验证
    const step4 = await testStep4(session, step3)

    // 步骤5: 填写电话号码（如果需要）
    const step5 = await testStep5(session, step4)

    // 步骤6: 选择办事处（如果需要）
    const step6 = await testStep6(session, step5)

    // 步骤7: 获取日历
    const step7 = await testStep7(session, step6)

    // 分析最终结果
    console.log('\n📊 诊断总结')
    console.log('='.repeat(60))
    console.log(`步骤1 (首页): ${step1.analysis.isHome ? '✓' : '✗'}`)
    console.log(`步骤2 (条款): ${step2.analysis.isTerms ? '✓' : '✗'}`)
    console.log(`步骤3 (个人信息): ${step3.analysis.isPersonalInfo ? '✓' : '✗'}`)
    console.log(`步骤4 (身份验证): ${step4.analysis.isIdentityCheck ? '✓' : '✗'}`)
    console.log(`步骤5 (电话填写): ${step5.analysis.isPhoneInput ? '⚠️ 已处理' : '✓ 跳过'}`)
    console.log(`步骤6 (办事处选择): ${step6.analysis.isOfficeSelect ? '⚠️ 已处理' : '✓ 跳过'}`)
    console.log(`步骤7 (日历页): ${step7.analysis.isCalendar ? '✓' : '✗'}`)

    // 最终状态分析
    if (step7.analysis.hasError || step7.analysis.hasBlocked) {
      console.log(`\n❌ 检测到问题:`)
      if (step7.analysis.hasBlocked) {
        console.log(`  - 可能被拦截（IP限制或重复登录）`)
      }
      if (step7.analysis.hasError) {
        console.log(`  - 页面包含错误信息`)
      }
    }
    else if (step7.analysis.isCalendar) {
      console.log(`\n✓ 成功到达日历页！`)
      if ('datesResult' in step7 && step7.datesResult && step7.datesResult.success && step7.datesResult.data) {
        const dateCount = step7.datesResult.data.length
        if (dateCount > 0) {
          console.log(`  ✓ 找到 ${dateCount} 个可用日期`)
        }
        else {
          console.log(`  ⚠️  当前月份没有可用日期`)
        }
      }
    }
    else {
      console.log(`\n⚠️  未到达日历页，当前页面状态:`)
      if (step7.analysis.isPhoneInput)
        console.log(`  - 需要填写电话`)
      if (step7.analysis.isOfficeSelect)
        console.log(`  - 需要选择办事处`)
    }

    console.log(`\n📁 所有快照已保存到: ${SNAPSHOT_DIR}`)
    console.log(`   请查看快照文件以获取详细信息`)
  }
  catch (error) {
    console.error('\n❌ 测试过程中出错:')
    console.error(error)
    throw error
  }
}

// 运行诊断
runDiagnosis().catch(console.error)
